﻿/* Created by Richard Fleming
 * Copyright 2008 Johnson County Community College
 * Free for non-commercial use
 */

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace XnaUtility.GameObjects
{
    public class Base2DObject : DrawableGameComponent
    {
        //public
        public Vector2 Location;
        public Vector2 Direction;
        public float Velocity { get; set; }
        public float Rotation { get; set; }
        public Rectangle Boundry;
        public SpriteBatch spriteBatch { get; set; }
        public Color Tint { get; set; }
        public bool Alive { get; set; }
       
        //Non-public
        protected Texture2D image;
        //private System.Timers.Timer batchTimer;
        private int failCount;
        protected Color[] colorData;

        public Base2DObject(Game game) 
            : base(game)
        {
            Location = Vector2.Zero;
            Boundry.X = (int)Location.X;
            Boundry.Y = (int)Location.Y;
            failCount = 0;
            Rotation = 0;
            Direction = Vector2.Zero;
            Velocity = 0.0f;
            Tint = Color.White;
            Alive = true;
        }

        /// <summary>
        /// Empty on purpose
        /// </summary>
        /// <param name="gameTime"></param>
        //public override void Update(GameTime gameTime)
        //{

        //    base.Update(gameTime);
        //}

        ///// <summary>
        ///// Empty on purpose
        ///// </summary>
        ///// <param name="gameTime">Current game time</param>
        //public override void Draw(GameTime gameTime)
        //{

        //    base.Draw(gameTime);
        //}

        protected override void LoadContent()
        {
            spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            if (spriteBatch == null)
            {
                //batchTimer = new System.Timers.Timer(10);
                //batchTimer.Elapsed += new System.Timers.ElapsedEventHandler(batchTimer_Elapsed);
                //batchTimer.Enabled = true;
                //batchTimer.Start();
            }
            base.LoadContent();
        }

        //void batchTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        //{
        //    failCount++;
        //    if (failCount > 100)
        //    {
        //        throw new Exception("Failed to aquire SpriteBatch in Base2DObject.  Did you remember to add it to the service list?");
        //    }
        //    else
        //    {
        //        spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
        //        //if (spriteBatch != null)
        //        //{
        //        //    batchTimer.Stop();
        //        //    batchTimer = null;
        //        //}
        //    }
        //}

        public void UpdateBoundry()
        {
            Boundry.X = (int)Location.X;
            Boundry.Y = (int)Location.Y;
        }

        /// <summary>
        /// Does a basic draw of the object.  Assumes there is an open SpriteBatch, and does not call Begin() or End()
        /// </summary>
        /// <param name="gameTime">Current game time</param>
        public virtual void DrawWithoutStart(GameTime gameTime)
        {
            spriteBatch.Draw(image, Location, Tint);
        }

        public void SetImage(Texture2D image)
        {
            this.image = image;
            Boundry.Width = image.Width;
            Boundry.Height = image.Height;
            colorData = new Color[image.Width * image.Height];
            image.GetData(colorData);
        }

        public bool IntersectBoundry(Base2DObject other)
        {
            return IntersectBoundry(other.Boundry);
        }

        public bool IntersectBoundry(Rectangle other)
        {
            return this.Boundry.Intersects(other);
        }

        //Source: http://creators.xna.com/en-US/tutorial/collision2dperpixeltransformed
        //Modified by Richard Fleming
        public bool IntersectPixels(Base2DObject other)
        {
            // Find the bounds of the rectangle intersection
            int top = Math.Max(this.Boundry.Top, other.Boundry.Top);
            int bottom = Math.Min(this.Boundry.Bottom, other.Boundry.Bottom);
            int left = Math.Max(this.Boundry.Left, other.Boundry.Left);
            int right = Math.Min(this.Boundry.Right, other.Boundry.Right);

            // Check every point within the intersection bounds
            for (int y = top; y < bottom; y++)
            {
                for (int x = left; x < right; x++)
                {
                    // Get the color of both pixels at this point
                    Color colorA = this.colorData[(x - this.Boundry.Left) +
                                         (y - this.Boundry.Top) * this.Boundry.Width];
                    Color colorB = other.colorData[(x - other.Boundry.Left) +
                                         (y - other.Boundry.Top) * other.Boundry.Width];

                    // If both pixels are not completely transparent,
                    if (colorA.A != 0 && colorB.A != 0)
                    {
                        // then an intersection has been found
                        return true;
                    }
                }
            }

            // No intersection found
            return false;
        }

    }
}
